package com.irdstudio.efp.nls.service.impl.yx;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.irdstudio.basic.framework.core.constant.BaseConstant;
import com.irdstudio.efp.console.service.facade.SCfgParamService;
import com.irdstudio.efp.console.service.vo.SCfgParamVO;
import com.irdstudio.efp.esb.common.constant.MsLoanConstant;
import com.irdstudio.efp.esb.common.constant.loan.PerLoanConstant;
import com.irdstudio.efp.esb.service.facade.EsbInvokeWrapper;
import com.irdstudio.efp.nls.service.facade.NlsQueueSoltComnService;
import com.irdstudio.efp.nls.service.facade.sx.NlsCreditInfoService;
import com.irdstudio.efp.nls.service.vo.sx.NlsCreditInfoVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.irdstudio.basic.framework.core.exception.BizException;
import com.irdstudio.basic.framework.core.util.StringUtil;
import com.irdstudio.basic.framework.core.util.TimeUtil;
import com.irdstudio.efp.console.service.facade.CustomerLimitInfoService;
import com.irdstudio.efp.console.service.facade.PrdInfoService;
import com.irdstudio.efp.console.service.vo.CustomerLimitInfoVO;
import com.irdstudio.efp.console.service.vo.PrdInfoVO;
import com.irdstudio.efp.esb.service.bo.req.loan.PerLoanSysLoanBalanceReqBean;
import com.irdstudio.efp.esb.service.bo.resp.loan.PerLoanSysLoanBalanceRespBean;
import com.irdstudio.efp.esb.service.facade.loan.PerLoanSysLoanBalanceService;
import com.irdstudio.efp.loan.service.facade.AccLoanService;
import com.irdstudio.efp.loan.service.vo.AccLoanVO;
import com.irdstudio.efp.nls.service.facade.NlsApplyInfoService;
import com.irdstudio.efp.nls.service.facade.ed.LimitControlsService;
import com.irdstudio.efp.nls.service.facade.ed.LmtRecoverRecordService;
import com.irdstudio.efp.nls.service.vo.NlsApplyInfoVO;

/**
 * 需求编号:【额度管控功能】
 * 开发人员：chenxuan
 * 创建日期：2019/8/8 16:08
 * 功能描述：统计已占用额度
 * 借据余额 + 在途金额：挂起、审批中、审批通过待放款 + 账务日期+1 0：00 到 当前时间内的 恢复金额 + 个贷系统已占用金额
 *
 * @version 0.1
 */
@Service("limitControlsService")
public class LimitControlsServiceImpl implements LimitControlsService {
    public final  String prdStatus = "2";
    public final  String loanCate = "001";
    public final String customerLimitInfoSts = "01";
    public final String  cusType = "02";
    public final String  cuarMd = "1";
    public final String  guarWay = "00";

    @Autowired
    @Qualifier("accLoanService")
    private AccLoanService accLoanService;

    @Autowired
    @Qualifier("nlsApplyInfoService")
    private NlsApplyInfoService nlsApplyInfoService;

    @Autowired
    @Qualifier("lmtRecoverRecordService")
    private LmtRecoverRecordService lmtRecoverRecordService;

    @Autowired
    @Qualifier("prdInfoService")
    private PrdInfoService prdInfoService;

    @Autowired
    @Qualifier("customerLimitInfoService")
    private CustomerLimitInfoService customerLimitInfoService;

    @Autowired
    @Qualifier("perLoanSysLoanBalanceService")
    private PerLoanSysLoanBalanceService perLoanSysLoanBalanceService;

    @Autowired
    @Qualifier("sCfgParamService")
    private SCfgParamService sCfgParamService;

    // 告警服务
    @Autowired
    @Qualifier("nlsQueueSoltComnService")
    private NlsQueueSoltComnService nlsQueueSoltComnService;

    @Autowired
    @Qualifier("nlsCreditInfoService")
    private NlsCreditInfoService nlsCreditInfoService;

    private static final Logger log = LoggerFactory.getLogger(LimitControlsServiceImpl.class);

    /**
     * 需求编号：【额度管控】
     * 问题编号：【在贷金额统计】
     * 开发人员：【chenxuan】
     * 创建/修改日期：【2019/8/19】
     * 修改描述：
     * @Param [nlsApplyInfoVO]
     * @return java.math.BigDecimal
     **/
    public BigDecimal getAvailAmt(NlsApplyInfoVO nlsApplyInfoVO) throws BizException{
        CustomerLimitInfoVO customerLimitInfoVO = new CustomerLimitInfoVO();
        customerLimitInfoVO.setSts(customerLimitInfoSts);
        customerLimitInfoVO.setCusType(cusType);
        BigDecimal availAmt = new BigDecimal("1");

        // 个贷查询贷款借据余额信息入参
		PerLoanSysLoanBalanceReqBean perLoanSysLoanBalanceReqBean = new PerLoanSysLoanBalanceReqBean();
		// 证件类型
        perLoanSysLoanBalanceReqBean.setCertTp(nlsApplyInfoVO.getCertType());
		// 证件号码
        perLoanSysLoanBalanceReqBean.setCertNo(nlsApplyInfoVO.getCertCode());
		// 担保方式
        perLoanSysLoanBalanceReqBean.setGuarMd(cuarMd);
        try {
            customerLimitInfoVO = customerLimitInfoService.queryByStsAndCusTyp(customerLimitInfoVO);
            if (customerLimitInfoVO.getQuotaLimiAmt() != null) {
                if(TimeUtil.compareDates(TimeUtil.getCurDate(),customerLimitInfoVO.getStrDt()) >-1 && TimeUtil.compareDates(TimeUtil.getCurDate(),customerLimitInfoVO.getEndDt()) < 1 ){
                    BigDecimal amtLimit = customerLimitInfoVO.getQuotaLimiAmt();
                    BigDecimal preOccAmt = this.getPreOccAmt(nlsApplyInfoVO.getCertCode(),nlsApplyInfoVO.getCertType());
                    // 个贷贷款余额汇总
                    BigDecimal otherSysAmt = BigDecimal.ZERO;

                    // 根据配置主键、参数值，查参数配置表
                    SCfgParamVO sCfgParamVO = new SCfgParamVO();
                    sCfgParamVO.setParamKey(PerLoanConstant.LOAN_SYS_LOAN_BALANCE_QUERY_SWITCH);
                    sCfgParamVO.setParamValue(BaseConstant.YES_Y);
                    sCfgParamVO = sCfgParamService.queryByCondition(sCfgParamVO);
                    if(Objects.nonNull(sCfgParamVO)) {
                        // 根据身份证、证件类型查询个贷查询贷款借据余额信息
                        PerLoanSysLoanBalanceRespBean perLoanSysLoanBalanceRespBean = null;
                        try {
                            //perLoanSysLoanBalanceRespBean = perLoanSysLoanBalanceService.applyPerLoanSysLoanBalance(reqSedCustomerCollectionBean);
                            EsbInvokeWrapper esbInvokeWrapper = new EsbInvokeWrapper(perLoanSysLoanBalanceService, perLoanSysLoanBalanceReqBean,
                                    nlsQueueSoltComnService);
                            perLoanSysLoanBalanceRespBean = (PerLoanSysLoanBalanceRespBean) esbInvokeWrapper.invoke3Threes();
                        } catch (Exception e) {
                            e.printStackTrace();
                            log.error(nlsApplyInfoVO.getApplySeq()+"------调用个贷查询贷款借据余额信息接口异常!!!" );
                            throw new BizException("调用个贷查询贷款借据余额信息接口异常!");
                        }
                        //Objects.requireNonNull(perLoanSysLoanBalanceRespBean);
                        //Objects.requireNonNull(perLoanSysLoanBalanceRespBean.getLoanBalSumr());
                        if(Objects.nonNull(perLoanSysLoanBalanceRespBean) && Objects.nonNull(perLoanSysLoanBalanceRespBean.getLoanBalSumr())) {
                            // 个贷贷款余额汇总
                            otherSysAmt = new BigDecimal(perLoanSysLoanBalanceRespBean.getLoanBalSumr());
                        }
                    }
                    availAmt= amtLimit.subtract(preOccAmt).subtract(otherSysAmt);
                    log.info(nlsApplyInfoVO.getApplySeq()+"已占用额度为"+preOccAmt+"当前申请额度为"+nlsApplyInfoVO.getApplyAmt()+"目前可用额度为" + availAmt);
                }
            }
            return availAmt;
        } catch (BizException e) {
            /**设置百度原因说明**/
            nlsApplyInfoVO.setBdReasonCode(MsLoanConstant.ReasonCodeMap.get("Other"));
            nlsApplyInfoVO.setBdReasonMsg(MsLoanConstant.ReasonMsgMap.get("Other"));
            e.printStackTrace();
            throw new BizException("调用个贷查询贷款借据余额信息接口异常!");
         } catch (Exception e) {
            /**设置百度原因说明**/
            nlsApplyInfoVO.setBdReasonCode(MsLoanConstant.ReasonCodeMap.get("Other"));
            nlsApplyInfoVO.setBdReasonMsg(MsLoanConstant.ReasonMsgMap.get("Other"));
            e.printStackTrace();
            throw new BizException("在贷金额统计查询异常");
        }
    }

/**
 * 需求编号：【额度管控】
 * 问题编号：【查询借据余额】
 * 开发人员：【chenxuan】
 * 创建/修改日期：【2019/8/14】
 * 修改描述：
 * @Param [certCode, cerType]
 * @return java.math.BigDecimal
 **/
    @Override
    public BigDecimal getPreOccAmt(String certCode, String cerType) throws BizException {
        BigDecimal sumAmt = BigDecimal.ZERO;
        try {
            //查询产品大类为 个人消费贷款的 产品
            log.info("开始进行额度统计,流水号:" + "证件类型" + certCode + "证件号码" + cerType);
            String prdId = this.queryPrdIdByLoanCate(prdStatus, loanCate, guarWay);
            // 查询借据余额
            BigDecimal loanBalance = queryPreOccAmt2(certCode, cerType, prdId);
            // 查询在途金额：挂起、审批中、审批通过待放款
            BigDecimal duringAmt = this.queryDuringAmt(certCode, cerType, prdId);
            // 查询额度恢复金额
            BigDecimal recoverAmt = this.queryRecoverAmt(certCode, cerType, prdId);
            // 统计全部金额
            sumAmt = loanBalance.add(duringAmt).subtract(recoverAmt);
            log.info("统计全部金额" + certCode + "证件号码" + cerType );
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("已占用额度查询异常");
        } finally {
            return sumAmt;
        }
    }

    /**
     * 状态新增了 14-非应计
     * 风控占用额度计算不应该包含当前审批金额
     * 占用额度 = 借据余额 + 在途金额 - 额度恢复金额 - 当前审批金额
     * @param certCode
     * @param cerType
     * @return
     * @throws BizException
     */
    @Override
    public BigDecimal getPreOccAmt2(String certCode, String cerType,BigDecimal applyAmt) throws BizException {
        BigDecimal sumAmt = BigDecimal.ZERO;
        try {
            //查询产品大类为 个人消费贷款的 产品
            log.info("开始进行额度统计,流水号:" + "证件类型" + certCode + "证件号码" + cerType);
            String prdId = this.queryPrdIdByLoanCate(prdStatus, loanCate, guarWay);
            // 查询借据余额
            BigDecimal loanBalance = queryPreOccAmt2(certCode, cerType, prdId);
            // 查询在途金额：挂起、审批中、审批通过待放款
            BigDecimal duringAmt = this.queryDuringAmt(certCode, cerType, prdId);
            // 查询额度恢复金额
            BigDecimal recoverAmt = this.queryRecoverAmt(certCode, cerType, prdId);
            // 统计全部金额
            sumAmt = loanBalance.add(duringAmt).subtract(recoverAmt).subtract(applyAmt);
            log.info("统计全部金额" + certCode + "证件号码" + cerType );
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("已占用额度查询异常");
        } finally {
            return sumAmt;
        }
    }

    /**
     * 需求编号：【额度管控】
     * 问题编号：【查询在途金额】
     * 开发人员：【chenxuan】
     * 创建/修改日期：【2019/8/14】
     * 修改描述：根据产品状态，贷款分类，担保方式查询产品代码
     *
     * @return java.math.BigDecimal
     * @Param [certCode, cerType, prdId]
     **/
    @Override
    public String queryPrdIdByLoanCate(String prdStatus, String loanCate,String guarWay) throws BizException {
        String prdId = "";
        try {
            //查询产品大类为 个人消费贷款的 产品
            PrdInfoVO prdInfoVO = new PrdInfoVO();
            prdInfoVO.setPrdStatus(prdStatus);
            prdInfoVO.setLoanCate(loanCate);
            prdInfoVO.setGuarWay(guarWay);
            List<PrdInfoVO> prdInfoVOS = prdInfoService.queryPrdType(prdInfoVO);
            StringBuffer prdIdStrs = new StringBuffer();
            for (PrdInfoVO infoVO : prdInfoVOS) {
                prdIdStrs.append("'" + infoVO.getPrdId() + "',");
            }
            prdId = prdIdStrs.substring(1, prdIdStrs.length() - 2) + "";
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("根据产品状态，贷款分类，担保方式查询产品代码失败！");
        } finally {
            return prdId;
        }
    }

    /**
     * 需求编号：【额度管控】
     * 问题编号：【查询在途金额】
     * 开发人员：【chenxuan】
     * 创建/修改日期：【2019/8/14】
     * 修改描述：查询在途金额：挂起、审批中、审批通过待放款
     *
     * @return java.math.BigDecimal
     * @Param [certCode, cerType, prdId]
     **/
    public BigDecimal queryDuringAmt(String certCode, String cerType, String prdId) throws BizException {
        BigDecimal duringAmt = BigDecimal.ZERO;
        try {
            NlsApplyInfoVO nlsApplyInfoVO = new NlsApplyInfoVO();
            nlsApplyInfoVO.setCertCode(certCode);
            nlsApplyInfoVO.setCertType(cerType);
            nlsApplyInfoVO.setPrdId(prdId);
            duringAmt = nlsApplyInfoService.queryDuringAmt(nlsApplyInfoVO);
            log.info("证件类型" + certCode + "证件号码" + cerType + "查询在途金额：挂起、审批中、审批通过待放款金额为" + duringAmt);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("证件类型" + certCode + "证件号码" + cerType + "查询在途金额：挂起、审批中、审批通过待放款失败！");
        } finally {
            return duringAmt;
        }
    }

    /**
     * 需求编号：【额度管控】
     * 问题编号：【查询借据余额】
     * 开发人员：【chenxuan】
     * 创建/修改日期：【2019/8/14】
     * 修改描述：查询借据余额
     *
     * @return java.math.BigDecimal
     * @Param [certCode, cerType, prdId]
     **/
    public BigDecimal queryPreOccAmt(String certCode, String cerType, String prdId) throws BizException {
        BigDecimal loanBalance = BigDecimal.ZERO;
        try {
            AccLoanVO accloanParam = new AccLoanVO();
            accloanParam.setCertCode(certCode);
            accloanParam.setCertType(cerType);
            accloanParam.setPrdId(prdId);
            loanBalance = accLoanService.queryPreOccAmt(accloanParam);
            log.info("证件类型" + certCode + "证件号码" + cerType + "借据余额为" + loanBalance);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("证件类型" + certCode + "证件号码" + cerType + "查询借据余额失败！");
        } finally {
            return loanBalance;
        }
    }

    public BigDecimal queryPreOccAmt2(String certCode, String cerType, String prdId) throws BizException {
        BigDecimal loanBalance = BigDecimal.ZERO;
        try {
            AccLoanVO accloanParam = new AccLoanVO();
            accloanParam.setCertCode(certCode);
            accloanParam.setCertType(cerType);
            accloanParam.setPrdId(prdId);
            loanBalance = accLoanService.queryPreOccAmt2(accloanParam);
            log.info("证件类型" + certCode + "证件号码" + cerType + "借据余额为" + loanBalance);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("证件类型" + certCode + "证件号码" + cerType + "查询借据余额失败！");
        } finally {
            return loanBalance;
        }
    }
    /**
     * 需求编号：【额度管控】
     * 问题编号：【查询额度恢复金额】
     * 开发人员：【chenxuan】
     * 创建/修改日期：【2019/8/14】
     * 修改描述：查询借据余额
     * 20200529 tiankuanguang 修改：账务日期+1，原来的只查询最大值
     *
     * @return java.math.BigDecimal
     * @Param [certCode, cerType, prdId]
     **/
    public BigDecimal queryRecoverAmt(String certCode, String cerType, String prdId) throws BizException {
        BigDecimal recoverAmt = BigDecimal.ZERO;
        try {
            Map<String, String> paramMap = new HashMap<>();
            paramMap.put("prdId", prdId);
            paramMap.put("certCode", certCode);
            paramMap.put("cerType", cerType);
            String bizDate = accLoanService.queryMaxBizdate(paramMap);
            // 额度恢复：查询账务日期+1 0：02 到 当前时间内的 恢复金额
            String startTime = TimeUtil.getCurDate() + " 00:02:00";
            if (StringUtil.isNotEmpty(bizDate)) {
//                startTime = bizDate + " 00:02:00";
                startTime = TimeUtil.addDay(bizDate,1);
            }
            String endTime = TimeUtil.getCurrentDateTime();
            paramMap.put("startTime", startTime);
            paramMap.put("endTime", endTime);
            recoverAmt = lmtRecoverRecordService.querRecoverAmt(paramMap);
            log.info("根据证件类型" + certCode + "证件号码" + cerType + "开始时间" + startTime + "结束时间" + endTime + "查询额度恢复金额为" + recoverAmt.toString());
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("证件类型" + certCode + "证件号码" + cerType + "额度恢复金额失败！");
        } finally {
            return recoverAmt;
        }
    }
    /**
     * 需求编号：【额度管控】
     * 问题编号：【判断是否在途】
     * 开发人员：【chenxuan】
     * 创建/修改日期：【2019/8/14】
     * 修改描述：
     *
     * @return java.math.BigDecimal
     * @Param [certCode, cerType, prdId]
     **/
    @Override
    public boolean isDuring(NlsApplyInfoVO nlsApplyInfoVO) throws BizException {
        boolean isDuring = false;
        try {
        String prdId = this.queryPrdIdByLoanCate("2", "001" ,guarWay);
        BigDecimal duringAmt = this.queryDuringAmt(nlsApplyInfoVO.getCertCode(),nlsApplyInfoVO.getCertType(),prdId);
        duringAmt= nlsApplyInfoVO.getApplyAmt().subtract(duringAmt);
        if(duringAmt.compareTo(BigDecimal.ZERO) != 0){
            isDuring = true;
        }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("证件类型" + nlsApplyInfoVO.getCertCode() + "证件号码" + nlsApplyInfoVO.getCertType() + "判断是否在途失败！");
        } finally {
            return isDuring;
        }
    }

    /**
     *
     * 问题编号：【判断是否在途】
     * 开发人员：【dengqiwen】
     * 创建/修改日期：【2020/07/29】
     * 修改描述：
     *
     **/
    @Override
    public boolean isCreditDuring(String certType,String certCode,String applySeq) throws BizException {
        boolean isDuring = false;
        try {
            String prdId = this.queryPrdIdByLoanCate("2", "001" ,guarWay);
            List<NlsCreditInfoVO> nlsCreditInfoVOS = nlsCreditInfoService.queryCreditDuring(certType, certCode,prdId,applySeq);
            if(nlsCreditInfoVOS.size()>0){
                isDuring = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("证件类型" + certType + "证件号码" + certCode + "判断是否在途授信失败！");
        }
        return isDuring;
    }


}
